package cn.flying.data.core.processor;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONPath;

/**
 * @author: admin
 * @date: 2025年09月29日 22:00
 * @version: 1.0
 */
@Component
public class JsonDataProcessor {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 解析JSON为数据库记录
     */
    public Map<String, Object> parseToDbRecord(String json, List<CompiledMapping> mappings) {
        Map<String, Object> dbRecord = new HashMap<>();
        JSONObject jsonObj = JSON.parseObject(json);

        for (CompiledMapping mapping : mappings) {
            try {
                Object value = JSONPath.eval(jsonObj, mapping.getJsonPath());
                Object dbValue = convertToDbType(value, mapping);
                dbRecord.put(mapping.getDbFieldName(), dbValue);

            } catch (Exception e) {
                handleMissingField(dbRecord, mapping, e);
                handleConversionError(dbRecord, mapping, e);
            }
        }

        return dbRecord;
    }

    /**
     * 类型转换为数据库类型
     */
    private Object convertToDbType(Object value, CompiledMapping mapping) {
        if (value == null) {
            return getDefaultValue(mapping);
        }

        try {
            String stringValue = value.toString();

            switch (mapping.getFieldType()) {
                case STRING:
                    return truncateString(stringValue, mapping.getFieldLength());

                case INTEGER:
                    return Integer.parseInt(stringValue);

                case LONG:
                    return Long.parseLong(stringValue);

                case BIG_DECIMAL:
                    return new BigDecimal(stringValue);

                case DATE:
                    return parseDate(stringValue, mapping.getDateFormat(), "yyyy-MM-dd");

                case DATETIME:
                    return parseDate(stringValue, mapping.getDateFormat(), "yyyy-MM-dd HH:mm:ss");

                case BOOLEAN:
                    return parseBoolean(stringValue);

                case TEXT:
                case CLOB:
                    return stringValue;

                default:
                    return value;
            }
        } catch (Exception e) {
            throw new RuntimeException(
                    "字段类型转换失败: " + mapping.getDbFieldName() + ", value: " + value, e);
        }
    }

    private String truncateString(String value, Integer maxLength) {
        if (maxLength != null && value.length() > maxLength) {
            logger.warn("字段值长度超限，进行截断: {} -> {}", value.length(), maxLength);
            return value.substring(0, maxLength);
        }
        return value;
    }

    private Date parseDate(String dateStr, String format, String defaultFormat) {
        if (dateStr == null || dateStr.trim().isEmpty()) {
            return null;
        }

        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format != null ? format : defaultFormat);
            sdf.setLenient(false);
            return sdf.parse(dateStr.trim());
        } catch (ParseException e) {
            throw new RuntimeException("日期解析失败: " + dateStr + ", format: " + format, e);
        }
    }

    private Boolean parseBoolean(String value) {
        if ("true".equalsIgnoreCase(value) || "1".equals(value)) {
            return true;
        } else if ("false".equalsIgnoreCase(value) || "0".equals(value)) {
            return false;
        }
        throw new RuntimeException("布尔值解析失败: " + value);
    }

    private Object getDefaultValue(CompiledMapping mapping) {
        if (mapping.getDefaultValue() != null) {
            try {
                // 递归调用转换默认值
                return convertToDbType(mapping.getDefaultValue(), mapping);
            } catch (Exception e) {
                logger.warn("默认值转换失败: {}", mapping.getDefaultValue(), e);
            }
        }
        return null;
    }

    private void handleMissingField(Map<String, Object> record, CompiledMapping mapping, Exception e) {
        if (mapping.isRequired()) {
            throw new RuntimeException("必填字段缺失: " + mapping.getJsonPath());
        }

        Object defaultValue = getDefaultValue(mapping);
        if (defaultValue != null) {
            record.put(mapping.getDbFieldName(), defaultValue);
            logger.debug("字段缺失，使用默认值: {}", mapping.getDbFieldName());
        }
    }

    private void handleConversionError(Map<String, Object> record, CompiledMapping mapping, Exception e) {
        if (mapping.isRequired()) {
            throw new RuntimeException("必填字段转换失败: " + mapping.getDbFieldName(), e);
        }

        Object defaultValue = getDefaultValue(mapping);
        record.put(mapping.getDbFieldName(), defaultValue);
        logger.warn("字段转换失败，使用默认值: {}", mapping.getDbFieldName(), e);
    }

    /**
     * 批量解析
     */
    public List<Map<String, Object>> batchParse(List<String> jsons, List<CompiledMapping> mappings) {
        return jsons.parallelStream()
                .map(json -> parseToDbRecord(json, mappings))
                .collect(Collectors.toList());
    }
}